use core::fmt::{Display, Formatter};
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::error::Error;
use crate::modeling::Value;

pub const SYSTEM_ROLE_KEY: &'static str = "system";
pub const USER_ROLE_KEY: &'static str = "user";
pub const ASSISTANT_ROLE_KEY: &'static str = "assistant";

//system user
#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "PromptTemplateItemBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct PromptTemplateItem {
    pub role: String,
    pub text: String,
    pub id: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "PromptTemplateBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct PromptTemplate {
    pub messages: Vec<PromptTemplateItem>,
    pub options: HashMap<String, String>,
}

impl PromptTemplate {
    pub fn new(system: &String, prompt: &String, options_str: &String) -> anyhow::Result<Self> {
        let mut options: HashMap<String, String> = HashMap::new();
        if options_str != "" {
            options = serde_json::from_str(options_str.as_str())
                .map_err(|err| anyhow::anyhow!("{}", err))?;
        }
        Ok(PromptTemplate {
            messages: vec![
                PromptTemplateItem {
                    id: None,
                    role: String::from("system"),
                    text: system.clone(),
                },
                PromptTemplateItem {
                    id: None,
                    role: String::from("user"),
                    text: prompt.clone(),
                },
            ],
            options: options,
        })
    }
}
